#include "llviewerprecompiledheaders.h"

#include "selfvoicing.h"

#include <sapi.h>
#include <functional>

using namespace std;

SelfVoicing* SelfVoicing::gSelfVoicingInstance = NULL; 

SelfVoicing::SelfVoicing()
{
	// Initialize COM
	switch (CoInitialize ( NULL ))
	{
	case S_OK:
		break;

	case S_FALSE:
		// Already initialised
		break;

	case RPC_E_CHANGED_MODE:
	default:
		// Already initialised with a different state
		break;
	}

	// Create the voice interface object
	CoCreateInstance ( CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&mVoice );
}

SelfVoicing::~SelfVoicing()
{
	// Shutdown the voice
	if ( mVoice != NULL )
	{
		mVoice -> Release ();
		mVoice = NULL;
	}

	// Shutdown COM
	CoUninitialize ();
}

SelfVoicing& SelfVoicing::getInstance(void)
{
	if (!gSelfVoicingInstance)
	{
		gSelfVoicingInstance = new SelfVoicing();
	}

	return (*gSelfVoicingInstance);
}

void s2ws(const string &s, wstring &out, const locale &loc = locale())
{
	out.reserve( out.size() + s.size() );

// [GARETH] I couldn't get this to compile, so use the longer form in a for loop
//	transform( s.begin(), s.end(), back_inserter(out), 
//		bind1st( mem_fun_ref( ctype<wchar_t>::widen ), use_facet< ctype<wchar_t> >(loc)) );

	for( string::const_iterator x = s.begin(); x != s.end(); ++x)
	{
		ctype<wchar_t>::_Elem c = use_facet< ctype<wchar_t> >(loc).widen(*x);
		out.push_back(c);
	}
}

void c2ws(const char s[], wstring &out, const locale &loc = locale())
{
	out.reserve( out.size() + strlen(s) );

	for( size_t x = 0; x < strlen(s); ++x)
	{
		ctype<wchar_t>::_Elem c = use_facet< ctype<wchar_t> >(loc).widen( s[x] );
		out.push_back(c);
	}
}

void SelfVoicing::Speak(LLString& text)
{
	wstring out;
	s2ws(text, out);
	mVoice->Speak( out.c_str(), SPF_ASYNC, NULL );
}

void SelfVoicing::Speak(const char text[])
{
	wstring out;
	c2ws(text, out);
	mVoice->Speak( out.c_str(), SPF_ASYNC, NULL );
}